package Wallpaper::Randomizer;
$VERSION = sprintf "%.3f", 1 + substr(q$Revision: 159 $,9)/1000;

use Wallpaper::Configuration qw( %datastore );
use Wallpaper::Tools qw( getfiletime getdir );
use vars qw( %datastore );

require Exporter;
@ISA       = qw( Exporter );
@EXPORT_OK = qw( randomfile );

use strict;

=item * randomfile

randomfile selects a random file from an array of filename.  It favors newer
files, and does so in the following manner.

First, all the files in the array have their timestamps read.  Each file +
timestamp is inserted into %firsthash.  %firsthash is then sorted, (by file
timestamp), and each file is re-inserted into %secondhash this time with a rank
multiplier.  So the oldest file gets a rank of 1, and if you have 20 files, the
newest is ranked 20.

Finally, %secondhash is parsed, and each file is inserted into a final selection
array.  It's reinserted over and over until it's rank decreases to zero.  This
means that your newest file is in the array 20 times (and your oldest 1 time).

Finally, we pick a file from the array at random.  Since we've stuffed the array
with many duplicates, newer files are chosen more often, and older files chosen
less often.

This works, but there *HAS* to be a better way of doing this.  PLEASE email me
any suggestions you have have.

This function accepts two parameters, an array of files to pick from, and the
"current" file being displayed.  It returns the new randomly selected photo
(with path).

=cut

sub randomfile {
    my @inhash  = @{ $_[0] };
    my $display = $_[1];
    my $photodir = $_[2];

    my $general_config = Wallpaper::Configuration->general;
    my $debug          = $general_config->{ 'debug' };
    my $time           = Wallpaper::Tools->timedata( localtime );
    #my $photodir       = $general_config->{ 'bgdir' } . "/" . $general_config->{ 'photoset' }[ $time->{ 'hour' } ];
    my $this_function  = ( caller( 0 ) )[3];

    print "                                  : $this_function (2) Getting Random File\n" if ( $debug ge "2" );

    my ( @badphotos, @files, $new, %firsthash, %secondhash, $ranking );

    push( @badphotos, $datastore{ $display }{ 'next' } )    if $datastore{ $display }{ 'next' };
    push( @badphotos, $datastore{ $display }{ 'current' } ) if $datastore{ $display }{ 'current' };
    push( @badphotos, $datastore{ $display }{ 'old1' } )    if $datastore{ $display }{ 'old1' };
    push( @badphotos, $datastore{ $display }{ 'old2' } )    if $datastore{ $display }{ 'old2' };
    push( @badphotos, $datastore{ $display }{ 'old3' } )    if $datastore{ $display }{ 'old3' };
    push( @badphotos, $datastore{ $display }{ 'old4' } )    if $datastore{ $display }{ 'old4' };

    print "                                  : $this_function (2) First Run, Getting Filetimes:\n" if ( $debug ge "3" );
    for my $file ( @inhash ) {
        my $timeref   = getfiletime( $photodir . "/" . $file );
        my $timestamp = $timeref->{ 'mtime' };

        my $ref = $firsthash{ $timestamp };
        $ref->{ 'age' }          = $timestamp;
        $ref->{ 'name' }         = $file;
        $firsthash{ $timestamp } = $ref;
        print "                                  : $this_function (4) $ref->{'age'} $ref->{'name'}\n" if ( $debug ge "4" );
    } ## end for my $file ( @inhash )

    print "                                  : $this_function (3) Second Run, Ranking Files:\n" if ( $debug ge "3" );
    foreach my $ref ( sort keys %firsthash ) {
        $ranking++;
        my $rank = sprintf( "%.3d", $ranking );
        my $hashfile = $firsthash{ $ref }{ 'name' };

        my $ref = $secondhash{ $hashfile };
        $ref->{ 'rank' }         = $rank;
        $ref->{ 'name' }         = $hashfile;
        $secondhash{ $hashfile } = $ref;
        print "                                  : $this_function (4) $ref->{'rank'} $ref->{'name'}\n" if ( $debug ge "4" );
    } ## end foreach my $ref ( sort keys...

    print "                                  : $this_function (3) Third Run, Stuffing selection array:\n" if ( $debug ge "3" );
    while ( my ( $source, $hashes ) = each %secondhash ) {
        my $times = $hashes->{ 'rank' };
        my $rank;
        print "                                  : $this_function (4) $source inserted into array $times times\n" if ( $debug ge "4" );
        while ( $times > $rank++ ) {
            push( @files, $source );
        }
    } ## end while ( my ( $source, $hashes...

    print "                                  : $this_function (3) Picking a random item from the BIG array (size: $#files elements) for $display\n"
      if ( $debug ge "4" );
    while ( 1 ) {
        my $index = rand @files;
        $new = $files[$index];
      last unless ( &comparelist( \@badphotos, $photodir . "/" . $new ) );
    }
    print "                                  : $this_function (2) Randomly selected new photo is $new for $display\n" if ( $debug ge "2" );

  return $new;
} ## end sub randomfile

=item * comparelist

Simple little function to compare a list of photos to a given photo, and return
true if there is a match.  Used to filter out photos that have been displayed
recently.

Two parameters, an array of "bad photos", and the current photo to compare to
the list of badphotos.  If a match is found, true is returned.  Otherwise it
returns nothing.

=cut

sub comparelist {
    my @badphotos = @{ $_[0] };
    my $selected  = $_[1];

    my $general_config = Wallpaper::Configuration->general;
    my $debug          = $general_config->{ 'debug' };
    my $this_function  = ( caller( 0 ) )[3];

    for my $photo ( @badphotos ) {
        chomp( $photo, $selected );
        if ( "$photo" eq "$selected" ) {
            print "                                  : $this_function (2) $photo matches $selected, picking again.\n" if ( $debug ge "2" );
          return 1;
        }
    }
  return undef;

} ## end sub comparelist

1;
